// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;

@ccclass
export default class ListViewCtrl extends cc.Component {

    // @property(cc.Node)
    // itemTemplate: cc.Node = null;

    @property(cc.ScrollView)
    scrollView: cc.ScrollView = null;

    @property
    spacing: number = 0; // space between each item

    @property
    componentStr: string = '';

    @property
    bufferZone: number = 0; // when item is away from bufferZone, we relocate it

    @property({
        type: [cc.Node]
    })
    items: cc.Node[] = [];

    private totalCount: number = 0; // how many items we need for the whole list

    private content: cc.Node;
    private spawnCount: number = 0; // how many items we actually spawn
    private itemHeight: number = 0;

    private updateTimer: number = 0;
    private updateInterval: number = 0;
    private lastContentPosY: number = 0;

    private itemDatas:any = null;
    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        this.content = this.scrollView.content;
        this.itemDatas = null;
        // this.items = []; // array to store spawned items
    	// this.initialize();
        // this.updateTimer = 0;
        // this.updateInterval = 0.2;
        // this.lastContentPosY = 0; // use this variable to detect if we are scrolling up or down
    }

    start () {

    }

    onEnable() {
        console.log("/...............");
    }

    update(dt) {
        if (this.itemDatas == null) {
            return;
        }
        if (this.totalCount <= this.spawnCount) {
            return;
        }
        this.updateTimer += dt;
        if (this.updateTimer < this.updateInterval) return; // we don't need to do the math every frame
        this.updateTimer = 0;
        let items = this.items;
        let buffer = this.bufferZone;
        let isDown = this.scrollView.content.y < this.lastContentPosY; // scrolling direction
        let offset = (this.itemHeight + this.spacing) * items.length;
        for (let i = 0; i < items.length; ++i) {
            let viewPos = this.getPositionInView(items[i]);

            if (isDown) {
                let item = items[i].getComponent(this.componentStr);
                let itemId = item.itemID - this.spawnCount;
                // if away from buffer zone and not reaching top of content
                if (viewPos.y < -buffer && itemId >= 0) {
                    items[i].y = items[i].y + offset;
                    item.updateItem(itemId, this.itemDatas[itemId]);
                }
                // if (viewPos.y < -buffer && items[i].y + offset < 0) {
                //     items[i].y = items[i].y + offset;
                //     let item = items[i].getComponent(this.componentStr);
                //     let itemId = item.itemID - items.length; // update item id
                //     item.updateItem(itemId, this.itemDatas[i]);
                // }
            } else {

                let item = items[i].getComponent(this.componentStr);
                let itemId = item.itemID + this.spawnCount;
                // if away from buffer zone and not reaching bottom of content
                if (viewPos.y > this.itemHeight && itemId < this.totalCount) {
                    items[i].y = items[i].y - offset;
                    item.updateItem(itemId, this.itemDatas[itemId]);
                }
                // if (viewPos.y > buffer && items[i].y - offset > -this.content.height) {
                //     items[i].y = items[i].y - offset;
                //     let item = items[i].getComponent(this.componentStr);
                //     let itemId = item.itemID + items.length;
                //     item.updateItem(itemId, this.itemDatas[i]);
                // }
            }
        }
        // update lastContentPosY
        this.lastContentPosY = this.scrollView.content.y;
        // this.lblTotalItems.textKey = "Total Items: " + this.totalCount;
    }

    public initialize() {
        // this.content.removeAllChildren();
        this.itemHeight = this.items[0].height;
        this.content.height = this.totalCount * (this.itemHeight + this.spacing) + this.spacing; // get total content height
        this.spawnCount = Math.min(this.items.length, this.totalCount);
        // this.items = [];
    	for (let i = 0; i < this.spawnCount; ++i) { // spawn items, we only need to do this once
    		// let item = cc.instantiate(this.itemTemplate);
    		// this.content.addChild(this.items[i]);
            // item.setPosition(0, -item.height * (0.5 + i) - this.spacing * (i + 1));
            this.items[i].active = true;
    		this.items[i].setPosition(0, -this.itemHeight * (i) - this.spacing * (i + 1));
    		this.items[i].getComponent(this.componentStr).updateItem(i, this.itemDatas[i]);
    	}
    }

    private getPositionInView(item) { // get item position in scrollview's node space
        let worldPos = item.parent.convertToWorldSpaceAR(item.position);
        let viewPos = this.scrollView.node.getChildByName('view').convertToNodeSpaceAR(worldPos);
        return viewPos;
    }

    public updateData(data) {
        this.itemDatas = data;
        if (data == null) {
            this.totalCount = 0;
        }else{
            this.totalCount = data.length;
        }

    }

    public refreshData(data) {
        this.itemDatas = data;
    //     let items = this.items;
        for (let i = 0; i < this.items.length; ++i) {
            let item = this.items[i].getComponent(this.componentStr);
            item.updateItem(item.itemID, this.itemDatas[item.itemID]);
        }
    }

    public toTop() {
        this.scrollView.scrollToTop(0.1);
        this.updateTimer = 0;
        this.updateInterval = 0.2;
        this.lastContentPosY = 0;
    }

    public getTotalCount() {
        return this.totalCount;
    }
}
